package com.hontech.bread.ui.dialog

import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.google.android.flexbox.FlexDirection
import com.google.android.flexbox.FlexWrap
import com.google.android.flexbox.FlexboxLayoutManager
import com.hontech.bread.R
import com.hontech.bread.utils.EmptyEdge
import com.hontech.bread.utils.log
import com.hontech.bread.utils.runIO
import com.hontech.bread.utils.stringById
import kotlinx.coroutines.CompletableDeferred
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileInputStream

private const val W = 600
private const val H = 500


class FileDialog(val path: String) : DraggableWindow(W, H, R.layout.dialog_file, false) {

    private val btnBack = view.findViewById<Button>(R.id.id_file_btn_back)
    private val btnClose = view.findViewById<Button>(R.id.id_file_btn_close)
    private val tvTitle = view.findViewById<TextView>(R.id.id_file_tv_title)
    private val rv = view.findViewById<RecyclerView>(R.id.id_file_rv)
    private val selectPromise = CompletableDeferred<File>()

    suspend fun open(): File {
        var current = File(path)
        val adapter = FileAdapter(scanFiles(path)) { adp, file ->
            if (file.isFile) {
                selectPromise.complete(file)
                dismiss()
                return@FileAdapter
            }
            val path = file.path
            tvTitle.text = path
            current = file
            log("add path $path")
            adp.update(path)
        }

        btnBack.setOnClickListener {
            val parent = current.parentFile ?: return@setOnClickListener

            val path = parent.path
            log("back path $path")
            tvTitle.text = path
            current = parent
            adapter.update(path)
        }

        btnClose.setOnClickListener {
            selectPromise.completeExceptionally(IllegalStateException(stringById(R.string.t1733460848_326)))
            dismiss()
        }

        tvTitle.text = path
        rv.adapter = adapter
        rv.layoutManager = FlexboxLayoutManager(view.context, FlexDirection.ROW, FlexWrap.WRAP)
        rv.edgeEffectFactory = EmptyEdge()
        showCenter()
        return selectPromise.await()
    }
}


private fun scanFiles(path: String): List<File> {
    log("scan path:$path")
    val list = ArrayList<File>()
    val file = File(path)
    val fs = file.listFiles() ?: return emptyList()
    for (f in fs) {
        if (f.isHidden) {
            continue
        }
        if (f.isDirectory || f.isFile) {
            list.add(f)
        }
    }
    log("files:${list.size}")
    return list
}

private class FileItem(view: View) : RecyclerView.ViewHolder(view) {

    private val btnIcon = view.findViewById<Button>(R.id.id_item_file_icon)
    private val tvName = view.findViewById<TextView>(R.id.id_item_file_tv_name)

    fun setUp(file: File, adapter: FileAdapter, onItemSelect: (FileAdapter, File) -> Unit) {
        if (file.isDirectory) {
            btnIcon.setBackgroundResource(R.drawable.btn_folder)
        } else {
            btnIcon.setBackgroundResource(R.drawable.btn_file)
        }
        btnIcon.setOnClickListener { onItemSelect(adapter, file) }
        tvName.text = file.name
    }
}

private class FileAdapter(
    private var files: List<File>,
    private val onItemSelect: (FileAdapter, File) -> Unit
) : RecyclerView.Adapter<FileItem>() {

    @SuppressLint("NotifyDataSetChanged")
    fun update(path: String) {
        files = scanFiles(path)
        notifyDataSetChanged()
    }

    override fun getItemCount(): Int {
        return files.size
    }

    override fun onBindViewHolder(holder: FileItem, position: Int) {
        holder.setUp(files[position], this, onItemSelect)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FileItem {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_file, parent, false)
        return FileItem(view)
    }
}


private var lastPath = "/storage"

suspend fun requiredFile(path: String): File {
    return FileDialog(path).open()
}

private fun changeExists() {
    lastPath = "/storage"
}

suspend fun readImage(): ByteArray {
    changeExists()

    val file = requiredFile(lastPath)
    val parent = file.parent
    if (parent != null) {
        lastPath = parent
    }

    return runIO {
        val input = FileInputStream(file)
        val buf = ByteArray(1024)
        val out = ByteArrayOutputStream()
        input.use {
            while (true) {
                val n = input.read(buf)
                if (n <= 0) {
                    break
                }
                out.write(buf, 0, n)
            }
            out.toByteArray()
        }
    }
}

